import * as grpc from '@grpc/grpc-js'
import {IHelloServer, HelloService} from '../proto/hello_grpc_pb'
import {EchoRequest} from "../proto/hello_pb";

const sleep = (n: number) => new Promise((r) => setTimeout(r, n))
const helloServer: IHelloServer = {
    /**
     * 响应客户端的单次请求,并返回单个信息
     * @param call 客户端的请求消息
     * @param callback 服务端的返回消息写入
     */
    echo: (call, callback) => {
        // 打印客户端的请求信息
        console.log(call.request.toObject())
        // 写入返回的消息
        callback(null, call.request)
    },
    /**
     * 接收到客户端的单个信息请求,服务端返回数据流
     * @param call 客户端的请求消息
     */
    serverStream: async (call) => {
        // 打印客户端的请求信息
        console.log(call.request.toObject())
        /* 流式返回信息给客户端,在客户端请求信息的基础上,增加递增数 */
        // 递增的数
        let num = 0
        // 获得原始的客户端请求信息
        let r = call.request
        const rawMeg = r.getMessage()
        // 循环进行流式数据传输
        for (let i = 0; i < 10; i++) {
            // 更新当前准备发送给客户端的信息
            const replay = new EchoRequest()
            replay.setMessage("hello " + rawMeg + num++);
            console.log(replay.toObject())
            // 写入到客户端
            call.write(replay)
            // await sleep(0)
        }
        // 流式传输完毕
        call.end()
    },
    /**
     * 接收客户端流式传输的信息,并返回最后1个接收到的信息
     * @param call
     * @param callback
     */
    clientStream: (call, callback) => {
        // 接收到的次数
        let count = 0
        // 记录每次客户端发送过来的值
        let d: any
        call.on('data', (dd) => {
            // 每次接收到客户端的值
            console.log(dd.toObject())
            d = dd

            ++count
        })

        call.on('error', (err) => {
            callback(err)
        })

        call.on('end', () => {
            // 客户端结束发送后,进行响应
            d.setMessage(`${d.getMessage()},count ${count}`)
            callback(null, d)
        })
    },
    duplexStream: (call) => {
        call.on('error', (err) => {
            call.emit('error', err)
        })

        call.on('end', () => {
            call.end()
        })

        // 接收到来自客户端的消息,进行响应
        call.on('data', (d) => {
            console.log(d.toObject())
            call.write(d)
        })
    },
}

const main = async () => {
    const server = new grpc.Server()
    server.addService(HelloService, helloServer)

    server.bindAsync(
        'localhost:8080',
        grpc.ServerCredentials.createInsecure(),
        () => {
            server.start()
        }
    )
}

main()
